package com.example.filter;

import com.example.common.Result;
import com.example.security.service.impl.UserDetailsServiceImpl;
import io.jsonwebtoken.Claims;
import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import com.example.until.JwtUtil;



@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    /**
     *  用于验证账号密码，本处于数据库交互
     */
//    @Autowired
//    private BaseUsersDao baseUsersDao;

    @Autowired
    @Qualifier("userDetailsServiceImpl")//需要指定注入的是那个类，避免报错。
    private UserDetailsServiceImpl userDetailsService;

    /**
     * 重写了 OncePerRequestFilter 类中的抽象方法 doFilterInternal。
     * OncePerRequestFilter 是 Spring Security 提供的一个基础类
     * ，设计用来确保过滤器在同一个请求中只执行一次。
     * @param request
     * @param response
     * @param filterChain
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, @NotNull HttpServletResponse response
            , @NotNull FilterChain filterChain) throws ServletException, IOException {
        // 检查是否是登录路径，若是则直接跳过 Token 验证
        String uri = request.getRequestURI();
        if (uri.equals("/user/login")) {
            filterChain.doFilter(request, response);
            return;
        }
        if (uri.equals("/greenHouse/get/average/time")) {
            filterChain.doFilter(request, response);
            return;
        }
        // 获取请求头的验证信息，即前端传回的token
        String token = request.getHeader("Authorization");
        System.out.println("----》     JwtAuthenticationTokenFilter，验证token过滤器，获取到的token值："+token);
        //为空时候继续下一步过滤链，即进行登录认证。后续进行格式验证，如果以bearer开始去掉前面的前缀
        if (!StringUtils.hasText(token) ) {
            System.out.println("----》     JwtAuthenticationTokenFilter，token验证："+"token为空！");
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"code\": 401, \"message\": \"Token为空，验证失败\"}");
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);  // 设置401 Unauthorized状态码
            return;
        }
        if (token.startsWith("Bearer ")) {
            System.out.println("----》     JwtAuthenticationTokenFilter，token格式验证中："+"token格式以Bearer开头，去掉开头！");
            token = token.substring(7);
        }

        //验证token是否过期
        boolean isValid = JwtUtil.validateJwtToken(token);//只在util中只验证是否过期了。
        if (!isValid) {
            System.out.println("----》     token验证失败，token过期。");
            response(response, "验证失败");
            return;
        }
        //获取token载荷中的用户信息
        Claims claims = JwtUtil.parseClaim(token).getPayload();
        String userid = claims.get("username").toString();

        //查询数据库中用户信息
        System.out.println("----》     数据库验证用户信息。"+"userid:"+userid);
        UserDetails userDetails = userDetailsService.loadUserByUsername(userid);
        System.out.println("----》     数据库中数据:"+userDetails.getUsername()+","+userDetails.getPassword());
        //设置安全上下文
        //创建一个自定义的 UserDetailsImpl 对象，将查询到的用户信息封装。
        //创建一个 UsernamePasswordAuthenticationToken 对象，表示用户的认证信息
        // ，并将其设置到 Spring Security 的 SecurityContextHolder 中，以便后续请求能够访问到用户的认证信息。
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        // 如果是有效的jwt，那么设置该用户为认证后的用户
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);

        //继续过滤链
        System.out.println("----》     jwt过滤器执行完毕！"+authenticationToken);
        filterChain.doFilter(request, response);
    }

    private void response(@NotNull HttpServletResponse response,String error) throws IOException {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 或者使用自定义状态码
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write("{\n" +
                "  \"states\": \""+error+"\",\n" +
                "  \"message\": \"无效token！\"\n" +
                "}");

    }

}
